var GridtreeSelector = '.tree';
var GridTreeControl = Class.create(GridControl, {
    selector:GridtreeSelector,
    opennodes:null,
    closednodes:null,
    separator:',',

    observeEvent: function($super)
    {
        $super();
        if (this.fresh)
        {
            this.observeTreeActions();
            this.loadTreeStates();
            this.observeDragdrop();
        }
    },

    observeDragdrop: function()
    {
        var me = this;
        this.findRow(' .node_icon').each(function(e){
            new Draggable(e, {ghosting: true, revert:true});
            Droppables.add(e, {
                accept: 'node_icon',
                hoverclass: 'drag_hover',
                onDrop: function(drag){
                    var drag_id = me.getRecordId(drag.up(me.rowSelector));
                    var drop_id = me.getRecordId(e.up(me.rowSelector));
                    me.view.insert('<input name="drag" type="hidden" value="'+drag_id+'"/>');
                    me.view.insert('<input name="drop" type="hidden" value="'+drop_id+'"/>');
                    me.setAction('UpdateParentId');
                    me.submit();
                }
            });
        })
    },

    observeTreeActions: function()
    {
        var me = this;
        this.findRow(' .node_button').invoke('observe', 'click', function(event){
            var element = event.element();
            if (element.hasClassName('node_icon') || element.tagName != 'DIV')
                return;
            me.treeExpand(this);
        });
        this.find('.expand_all').invoke('observe', 'click', this.treeExpandAll.bind(this));
        this.find('.collapse_all').invoke('observe', 'click', this.treeCollapsedAll.bind(this));
    },

    treeExpandAll: function()
    {
        this.emptyTreeStates();
        this.view.insert('<input name="expand_all" type="hidden" value="1"/>');
        this.submit();
    },

    treeCollapsedAll: function()
    {
        this.emptyTreeStates();
        this.submit();
    },

    treeExpand: function(e)
    {
        var id = this.getRecordId(e.up(this.rowSelector));
        if (e.hasClassName('node_expand'))
            this.addOpenNode(id);
        else
            this.removeOpenNode(id);
        this.treeInputStates();

        if (e.hasClassName('node_leaf'))
        {
            this.treeToogleNodeIcon(e);
            return;
        }

        this.submit();
    },

    treeToogleNodeIcon: function(e)
    {
        e.toggleClassName('node_expand').toggleClassName('node_collapse');
    },

    emptyTreeStates: function()
    {
        this.findOne('input.open_nodes').value = '';
        this.findOne('input.closed_nodes').value = '';
    },

    treeInputStates: function()
    {
        this.findOne('input.open_nodes').value = this.opennodes.keys().join(this.separator);
        this.findOne('input.closed_nodes').value = this.closednodes.keys().join(this.separator);
    },

    loadTreeStates: function()
    {
        if (!this.findOne('input.open_nodes')) return;

        this.opennodes = this.findOne('input.open_nodes').value.hash(this.separator);
        this.closednodes = this.findOne('input.closed_nodes').value.hash(this.separator);
    },

    addOpenNode: function(id)
    {
        this.opennodes.set(id, id);
        this.closednodes.unset(id);
    },

    removeOpenNode: function(id)
    {
        this.closednodes.set(id, id);
        this.opennodes.unset(id);
    }
});